/**
 * Copyright (c) 2012 Nokia Corporation. 
 */

package com.nokia.example.tictactoe.ui;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;

import com.nokia.example.tictactoe.engine.BasicGameManager;
import com.nokia.example.tictactoe.engine.GameModel;
import com.nokia.example.tictactoe.engine.AbstractGameManager;
import com.nokia.example.tictactoe.engine.IGameModelListener;
import com.nokia.example.tictactoe.engine.NetworkGameManager;

/**
 * The game view.
 */
public class GameView
	extends Canvas
	implements IGameModelListener
{
	// Members
	private GameModel _gameModel = null;
	private GameGrid _gameGrid = null;
	private AbstractGameManager _gameManager = null;
	private InfoLabel _infoLabel = null;
	
	/**
	 * Constructor.
	 */
	public GameView() {
	}

	/**
	 * From Canvas.
	 */
	protected void paint(Graphics graphics) {
		// The items (GameGrid and InfoLabel) are derived from
		// CanvasGraphicsItem and handle their own drawing so nothing needs to
		// be done here.
	}

	/**
	 * From Canvas.
	 */	
	protected void pointerPressed(int x, int y) {
		if (_gameManager.gameOngoing()) {
			_gameGrid.onPressed(x - _gameGrid.getPositionX(),
								y - _gameGrid.getPositionY());
		}
	}

	/**
	 * From Canvas.
	 */	
	protected void pointerReleased(int x, int y) {
		_gameGrid.onReleased(x - _gameGrid.getPositionX(), y - _gameGrid.getPositionY());
	}
	
	/**
	 * From Canvas.
	 */
	protected void pointerDragged(int x, int y) {
	}
	
	/**
	 * Initializes the game view.
	 */
	public void init() {
		if (_gameModel == null) {
			final int screenHeight = getHeight();
			
			_gameModel = GameModel.instance(this);
			_gameGrid = GameGrid.newDefaultSizeGrid(_gameModel);
			setGameManager(AbstractGameManager.NETWORK);
			
			// Parent must be set before any other operation is done with the
			// canvas graphics item
			_gameGrid.setParent(this);
			_gameGrid.setPosition(0, (screenHeight - GameGrid.BOARD_SIZE) / 2);
			
			_infoLabel = new InfoLabel(240, 40);
			_infoLabel.setParent(this);
			_infoLabel.setPosition(0, 0);
			_infoLabel.setVisible(true);
		}
		
		_gameGrid.setVisible(true); // Must be set to true
	}
	
	/**
	 * Sets the game manager.
	 * @param type The type of game manager to set.
	 */
	public void setGameManager(final int type) {
		System.out.println("GameView::setGameManager(): "
				+ ((type == AbstractGameManager.BASIC) ? "BASIC" : "NETWORK"));
		
		if (_gameManager != null) {
			if (type == _gameManager.type()) {
				return;
			}
			
			if (_gameManager.gameOngoing()) {
				_gameManager.endGame();
			}
		}
		
		if (type == AbstractGameManager.BASIC) {
			_gameManager = BasicGameManager.instance(_gameModel);
			_gameGrid.setGameManager(_gameManager);
		}
		else { // Treat NETWORK as default
			_gameManager = NetworkGameManager.instance(_gameModel);
			_gameGrid.setGameManager(_gameManager);
		}
	}
	
	/** 
	 * @return The current game manager.
	 */
	public AbstractGameManager gameManager() {
		System.out.println("GameView::gameManager(): Will return manager of type "
				+ ((_gameManager.type() == AbstractGameManager.BASIC) ? "BASIC" : "NETWORK"));
		return _gameManager;
	}
	
	/**
	 * @return The game model instance or null if not created.
	 */
	public final GameModel gameModel() {
		return _gameModel;
	}
	
	/** 
	 * @return True if a game is ongoing, false otherwise.
	 */
	public final boolean gameOngoing() {
		if (_gameManager != null) {
			return _gameManager.gameOngoing();
		}
		
		return false;
	}

	/* Methods from IGameModelListener. */
	
	public void onWhoseTurnChanged(int whoseTurn) {
		if (_infoLabel == null) {
			return;
		}
		
		if (_gameManager.gameOngoing()) {
			if (whoseTurn != GameModel.MARK_EMPTY
					&& whoseTurn == _gameModel.playerMark())
			{
				if (_gameModel.gridIsEmpty()) {
					_infoLabel.setText("Your turn, your mark is " + 
						((whoseTurn == GameModel.MARK_X) ? "X" : "O"));
				}
				else {
					_infoLabel.setText("Your turn");
				}
			}
			else {
				_infoLabel.setText("Waiting for opponent");
			}
		}
		
		repaint();
	}
	
	public void onGameOver(int winner) {
		if (winner == GameModel.MARK_EMPTY) {
			_infoLabel.setText("It's a tie!");
		}
		else {
			if (winner == _gameModel.playerMark()) {
				_infoLabel.setText("You won!");
			}
			else {
				_infoLabel.setText("You lost!");
			}
		}
		
		repaint();
	}
	
	public void onGameSpecificationsChanged() {
		if (_gameManager.gameOngoing()) {
			if (_gameManager.type() == AbstractGameManager.BASIC) {
				_gameManager.startGame();
			}
			else {
				_gameManager.onGameOver();
			}
		}
	}	
	
	public void onGameModelChanged() {
		repaint();
	}
}
